<?php
/*
 * Copyright (c) 2013 Eugene Kuzmenko
 *
 * Permission  is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in  the Software without restriction, including without limitation the rights
 * to  use,  copy,  modify,  merge, publish, distribute, sublicense, and/or sell
 * copies  of  the  Software,  and  to  permit  persons  to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The  above  copyright  notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE  SOFTWARE  IS  PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED,  INCLUDING  BUT  NOT  LIMITED  TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS  FOR  A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS  OR  COPYRIGHT  HOLDERS  BE  LIABLE  FOR  ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * For more information, see <http://www.aljey.com>.
 */

namespace Al\HTTP\Lib;

use Al\Core\Lib\Service;

/**
 * A response object.
 *
 * @author Eugene Kuzmenko <mail@aljey.com>
 */
class Response {

  /**
   * @var string
   */
  private $data;

  /**
   * @var string
   */
  private $extension;

  /**
   * @var array Static cache configuration.
   */
  private static $cached_routes = array();

  /**
   * @var bool True to allow accelerated downloads if the server software
   *           allows.
   *           It almost always best to keep this setting on except in those
   *           cases when the response status code is not successful.
   */
  private $accelerate = true;

  /**
   * @param string $data [optional]
   * @param string $extension [optional]
   */
  public function __construct($data = '', $extension = 'html') {
    $this->data = $data;
    $this->extension = $extension;
  }

  /**
   * Returns the response data.
   *
   * @return string
   */
  public function getData() {
    return $this->data;
  }

  /**
   * Renders itself to the browser.
   *
   * @param Route $route
   */
  public function render(Route $route) {
    $location = Service::get('http.server.location');
    $id = md5($location);
    $file = "cache/$id.$this->extension";
    if ($route->cache) {
      $cached_routes = &self::getCachedRoutes();
      $cached_routes[$id] = array(
        'uri' => $location,
        'type' => $this->extension,
        'file' => $file,
      );
      self::saveCachedRoutes();
    } else {
      @mkdir('cache', 0777, true);
    }
    file_put_contents($file, $this->data);
    include 'download.php';
    download($file, $this->extension, $this->accelerate);
  }

  /**
   * Removes a resource from the static cache.
   *
   * @param string $location [optional] A full URI (as seen in the browser
   *                         location bar) that is going to be removed from
   *                         cache, defaults to the current location.
   */
  public static function clearCache($location = '') {
    if (!$location) $location = Service::get('http.server.location');
    $id = md5($location);
    $files = glob("cache/$id.*");
    @unlink($filename = $files[0]);
    $cached_routes = &self::getCachedRoutes();
    if (isset($cached_routes[$id])) {
      unset($cached_routes[$id]);
      self::saveCachedRoutes();
    }
  }

  /**
   * Retrieves the static cache configuration.
   *
   * @return array Static cache configuration.
   */
  public static function &getCachedRoutes() {
    if (!self::$cached_routes) {
      @mkdir('cache', 0777, true);
      if (is_file('cache/routes.php')) {
        self::$cached_routes = (array)include 'cache/routes.php';
      }
    }
    return self::$cached_routes;
  }

  /**
   * Saves the static cache configuration.
   */
  public static function saveCachedRoutes() {
    file_put_contents('cache/routes.php', "<?php\nreturn " .
      var_export(self::$cached_routes, true) . ';');
  }

  /**
   * Completely empties the static cache. Use with caution.
   * The same thing can be achieved by simply deleting the cache directory
   * manually.
   */
  public static function flushCache() {
    if (is_dir('cache')) {
      $files = glob('cache/*');
      foreach ($files as $file) unlink($file);
      rmdir('cache');
      self::$cached_routes = array();
    }
  }

  /**
   * Returns the value of accelerate.
   *
   * @return boolean
   */
  public function isAccelerate() {
    return $this->accelerate;
  }

  /**
   * Changes the value of accelerate.
   *
   * @param boolean $accelerate
   * @return $this
   */
  public function setAccelerate($accelerate) {
    $this->accelerate = $accelerate;
    return $this;
  }

}